package com.ck.chuangke.controller;

import com.alibaba.fastjson.JSONObject;
import com.ck.cache.RedisCacheDao;
import com.ck.chuangke.service.CkCompanyService;
import com.ck.common.service.OperationLogService;
import com.ck.common.service.ResolveExcelService;
import com.ck.common.service.UserService;
import com.ck.constant.*;
import com.ck.exception.ControllerException;
import com.ck.exception.ServiceException;
import com.ck.export.util.SimpleExportUtil;
import com.ck.jwt.JwtUtil;
import com.ck.model.chuangke.vo.CkCompanyListVO;
import com.ck.model.chuangke.vo.CkDeviceCodeListExportVO;
import com.ck.model.common.Company;
import com.ck.model.common.OperationLog;
import com.ck.model.common.User;
import com.ck.model.common.page.PageInfo;
import com.ck.model.common.sys.JsonResponse;
import com.ck.util.HttpUtils;
import com.google.common.collect.Lists;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.OutputStream;
import java.util.List;
import java.util.Map;

/**
 * @ClassName CkCompanyController
 * @Description 创客管理后台-商家管理
 * @Author HanQinrui
 * @Date 2018/6/22 17:27
 * @Version 1.0
 **/
@Controller
@RequestMapping(value = "/ckCompany")
public class CkCompanyController {
    private Logger logger = LoggerFactory.getLogger(CkProgramController.class);
    @Autowired
    private CkCompanyService ckCompanyService;
    @Autowired
    private UserService userService;
    @Autowired
    private OperationLogService operationLogService;
    @Autowired
    private ResolveExcelService resolveExcelService;
    @Autowired
    private RedisCacheDao redisCacheDao;

    /**
     * 商家列表分页查询
     * @param companyName 商家名称
     * @param mobilePhone 手机号码
     * @param model
     * @param pageNum 当前页
     * @param pageSize 每页条数
     * @return
     */
    @RequestMapping(value = "/listByPage")
    public String listByPage(String companyName, String mobilePhone, Model model, Integer pageNum, Integer pageSize) {
        try {
            pageNum = (pageNum == null ? PageConstant.DEFAULT_PAGE_NUM : pageNum);
            pageSize = (pageSize == null ? PageConstant.DEFAULT_PAGE_SIZE : pageSize);
            PageInfo<CkCompanyListVO> pageInfo = ckCompanyService.listByPage(companyName, mobilePhone, pageNum, pageSize);
            model.addAttribute("pageNum", pageNum);
            model.addAttribute("pageSize", pageSize);
            model.addAttribute("result", pageInfo.getList());
            model.addAttribute("total", pageInfo.getTotal());
            model.addAttribute("companyName", companyName);
            model.addAttribute("mobilePhone", mobilePhone);
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("CkCompanyController listByPage 商家列表分页查询失败:" + e.getMessage());
        }
        return "ck/ck_company_list";
    }

    /**
     * 导出商家列表
     * @param companyName 商家名称
     * @param mobilePhone 手机号
     * @param response 响应
     */
    @RequestMapping(value = "/exportCkCompany")
    public void exportCompanyCk(String companyName, String mobilePhone, HttpServletResponse response) {
        try (OutputStream out = response.getOutputStream()) {
            List<CkCompanyListVO> ckCompanyListVOList = ckCompanyService.listExportCompany(companyName, mobilePhone);
            //设置输出类型
            response.setContentType("application/vnd.ms-excel;charset=utf-8");
            //设置文件名
            response.setHeader("Content-Disposition", "attachment;filename=" + new String(("创客商家列表.xls").getBytes(), "ISO-8859-1"));
            SimpleExportUtil.exportToExcel(ckCompanyListVOList, "创客商家列表").write(out);
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("CkCompanyController exportCompanyCk 导出创客商家列表失败：" + e.getMessage());
        }
    }

    /**
     * 查询商家详情页
     * @param companyId 商家id
     * @return
     */
    @RequestMapping(value = "/getCompanyInfoDetail")
    public Object getCompanyInfoDetail(String companyId, Model model) {
        if (StringUtils.isBlank(companyId)) {
            model.addAttribute("errorCode",ResponseConstant.CODE_FAIL);
            model.addAttribute("errorMsg",ResponseConstant.MSG_PARAM_ERROR);
            return "ck/ck_company_detail";
        }
        Company company = new Company();
        try {
            company = ckCompanyService.getCompanyInfoById(companyId);
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("CkCompanyController getCompanyInfoDetail 查询商家详情页失败：" + e.getMessage());
            model.addAttribute("errorCode",ResponseConstant.CODE_FAIL);
            model.addAttribute("errorMsg",ResponseConstant.MSG_ERROR);
            return "ck/ck_company_detail";
        }
        if(company == null) {
            model.addAttribute("errorCode",ResponseConstant.CODE_FAIL);
            model.addAttribute("errorMsg","该商家不存在，请刷新后重试");
            return "ck/ck_company_detail";
        }
        model.addAttribute("errorCode",ResponseConstant.CODE_SUCCESS);
        model.addAttribute("company",company);
        return "ck/ck_company_detail";
    }

    /**
     * 修改商家详细信息
     * @param company 商家信息
     * @return
     */
    @RequestMapping(value = "/updateCompany")
    @ResponseBody
    public Object updateCompany(Company company, HttpServletRequest request) {
        //验证参数
        if (company == null) {
            return new JsonResponse(ResponseConstant.CODE_FAIL, "参数不能为空");
        }
        //验证参数
        if (company.getCompanyId() == null || StringUtils.isBlank(company.getCompanyName())
                || StringUtils.isBlank(company.getCompanyCode())|| StringUtils.isBlank(company.getLoginUserName())
                || StringUtils.isBlank(company.getBusinessLicenseNo())
                || StringUtils.isBlank(company.getContacts()) || StringUtils.isBlank(company.getMobilePhone())
                || StringUtils.isBlank(company.getBusinessLicenseUrl()) || StringUtils.isBlank(company.getCompanyLogoUrl())
                || StringUtils.isBlank(company.getLegalPersonIdFrontUrl()) || StringUtils.isBlank(company.getLegalPersonIdBackUrl())) {
            return new JsonResponse(ResponseConstant.CODE_FAIL, "参数不能为空");
        }
        try {
            // 重复性验证
            String companyName = company.getCompanyName();
            Company companyRepeat = ckCompanyService.getCompanyCountByCompanyName(companyName);
            if(companyRepeat != null && (!companyRepeat.getCompanyId().equals(company.getCompanyId()))) {
                return new JsonResponse(ResponseConstant.CODE_FAIL, "商家名称重复，请重新输入");
            }
            ckCompanyService.updateCompany(company, request);
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("CkCompanyController updateCompany 修改商家详细信息失败：" + e.getMessage());
            return new JsonResponse(ResponseConstant.CODE_FAIL,"修改商家详细信息失败");
        }
        return "";
    }

    /**
     * 新增商家跳转
     * @return
     */
    @RequestMapping(value = "/addCompanyForward")
    public Object addCompanyForward() {
        return "ck/ck_company_add";
    }

    /**
     * 新增商家
     * @param company 商家信息
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/addCompany")
    public Object addCompany(Company company, String userNamePre, String excelDeviceCode, HttpServletRequest request) {
        //验证参数
        if (company == null) {
            return new JsonResponse(ResponseConstant.CODE_FAIL, "参数不能为空");
        }
        //验证参数
        if (StringUtils.isBlank(company.getCompanyName()) || StringUtils.isBlank(company.getLoginUserName())
                || StringUtils.isBlank(company.getLoginPassword()) || StringUtils.isBlank(company.getBusinessLicenseNo())
                || StringUtils.isBlank(company.getContacts()) || StringUtils.isBlank(company.getMobilePhone())
                || StringUtils.isBlank(company.getBusinessLicenseUrl()) || StringUtils.isBlank(company.getCompanyLogoUrl())
                || StringUtils.isBlank(company.getLegalPersonIdFrontUrl()) || StringUtils.isBlank(company.getLegalPersonIdBackUrl())
                || StringUtils.isBlank(userNamePre)) {
            return new JsonResponse(ResponseConstant.CODE_FAIL, "参数不能为空");
        }
        try {
            // 重复性验证
            String companyName = company.getCompanyName();
            Company companyRepeat = ckCompanyService.getCompanyCountByCompanyName(companyName);
            if(companyRepeat != null) {
                return new JsonResponse(ResponseConstant.CODE_FAIL, "商家名称重复，请重新输入");
            }
            String loginUserName = company.getLoginUserName();
            User userRepeat = userService.getUserByUserName(loginUserName);
            if(userRepeat != null) {
                return new JsonResponse(ResponseConstant.CODE_FAIL, "登录账号重复，请重新输入");
            }
            // 拼接登录账号
            String userNameSuf = company.getLoginUserName();
            loginUserName = userNamePre + userNameSuf;
            company.setLoginUserName(loginUserName);
            // 添加商家
            ckCompanyService.addCompany(company, excelDeviceCode, request);
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("CkCompanyController addCompany 新增商家失败：" + e.getMessage());
            return new JsonResponse(ResponseConstant.CODE_FAIL,"新增商家失败");
        }
        return "";
    }

    /**
     * 代运营
     * @param companyCode 商家代码
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/agentOperate")
    public Object agentOperate(HttpServletRequest request, String companyCode, String companyName) {
        User loginUser = (User) request.getSession().getAttribute(RequestConstant.SESSION_KEY_USER);
        //验证参数
        if (StringUtils.isBlank(companyCode)) {
            return new JsonResponse(ResponseConstant.CODE_FAIL, "参数不能为空");
        }
        // 查找该商家代码对应的用户超级管理员信息
        User adminUser = ckCompanyService.getAdminUserByCompanyCode(companyCode);
        if(adminUser == null) {
            return new JsonResponse(ResponseConstant.CODE_FAIL, "操作失败，未找到该商家的超级管理员");
        }
        //将用户放入sessoin中
        request.getSession().setAttribute(RequestConstant.SESSION_KEY_USER, adminUser);

        UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(adminUser.getUserName(), adminUser.getPassword());
        Subject subject = SecurityUtils.getSubject();
        try {
            subject.login(usernamePasswordToken);
        } catch (UnknownAccountException e) {
            //账户不存在
            return new JsonResponse(ResponseConstant.CODE_FAIL, "用户不存在");
        } catch (IncorrectCredentialsException e) {
            //密码错误
            return new JsonResponse(ResponseConstant.CODE_FAIL, "用户名或密码错误");
        }
        //删除操作人的token
        Object tokenRedis = redisCacheDao.getCache(CacheConstant.CK_TOKEN_USER_MAPPING, loginUser.getUserName());
        if (null != tokenRedis) {
            redisCacheDao.deleteByKey(CacheConstant.CK_TOKEN_CACHE_NAME, tokenRedis);
            redisCacheDao.deleteByKey(CacheConstant.CK_TOKEN_USER_MAPPING, loginUser.getUserName());
        }
        //写入redis, token为key
        String token = JwtUtil.sign(adminUser.getUserName(), adminUser.getPassword());
        redisCacheDao.putCache(CacheConstant.CK_TOKEN_CACHE_NAME, token,
                JSONObject.toJSONString(adminUser), CacheConstant.CACHE_EXPIRE_SECONDS);
        redisCacheDao.putCache(CacheConstant.CK_TOKEN_USER_MAPPING, adminUser.getUserName(), token, CacheConstant.CACHE_EXPIRE_SECONDS);

        // 保存操作日志
        OperationLog operationLog = new OperationLog();
        operationLog.setCopmanyCode(loginUser.getCompanyCode());
        operationLog.setOperationContent("创客后台管理员：" + loginUser.getUserName() + "对商家:" + companyName + "进行了代运营");
        operationLog.setOperationStatus(BusinessConstant.OPERATION_LONG_OPERATION_STATUS_SUCCESS);
        operationLog.setOperationTime(System.currentTimeMillis());
        operationLog.setOperationModule(ModuleConstant.MODULE_COMPANY);
        operationLog.setRealname(loginUser.getRealname());
        operationLog.setUserName(loginUser.getUserName());
        operationLog.setOperationIp(HttpUtils.getRemortIP(request));
        operationLogService.saveOperationLog(operationLog);
        return "";
    }

    /**
     * @Description 上传图片
     * @Param [files, request]
     * @return java.lang.Object
     * @Date 2018/7/24 18:15
     * @Author HanQinrui
     **/
    @ResponseBody
    @RequestMapping(value = "/upload", method = RequestMethod.POST)
    public Object uploadPicture(@RequestParam("files") MultipartFile files, HttpServletRequest request) {
        try {
            List msgList = Lists.newArrayList();
            Map<String, Object> fileMsgMap = ckCompanyService.savePicture(files, request);
            msgList.add(fileMsgMap);
            return msgList;
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("CkCompanyController uploadPicture 上传图片失败：" + e.getMessage());
            return e;
        }
    }

    /**
     * 上传机器码
     * @param file excel文件
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/uploadExcel", method = RequestMethod.POST)
    public Object uploadExcel(@RequestParam("files") MultipartFile file) {
        List<String> excelDeviceCodeList = null;
        List<String> repeatList = Lists.newArrayList();
        try {
            // 查询所有已绑定商家的终端机器码列表
            List<String> oldCompanyDeviceCodeList = ckCompanyService.getCompanyDeviceCodeList();
            // 解析Excel文件
            excelDeviceCodeList = resolveExcelService.resolveExcel(file);
            // 查找重复的机器码
            for(String str : excelDeviceCodeList) {
                if (oldCompanyDeviceCodeList.contains(str)) {
                    repeatList.add(str);
                }
            }
        } catch (ServiceException e) {
            e.printStackTrace();
        }
        if(repeatList.size() > 0 || !repeatList.isEmpty()) {
            // 上传失败
            String repeatDeviceCodes = com.ck.util.StringUtils.listToFormatString(repeatList,",");
            return new JsonResponse(ResponseConstant.CODE_FAIL,"机器码：" + repeatDeviceCodes + "重复，请重新上传");
        } else {
            // 上传成功
            String deviceCodes = com.ck.util.StringUtils.listToFormatString(excelDeviceCodeList,",");
            return new JsonResponse(ResponseConstant.CODE_SUCCESS, deviceCodes,"上传成功");
        }
    }

    /**
     * 修改机器码文件
     * @param excelCompanyCode 商家代码
     * @param excelDeviceCode 机器码(用逗号隔开)
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/updateDeviceCode")
    public Object updateDeviceCode(String excelCompanyCode, String excelDeviceCode, HttpServletRequest request) {
        //验证参数
        if (StringUtils.isBlank(excelCompanyCode) || StringUtils.isBlank(excelDeviceCode)) {
            return new JsonResponse(ResponseConstant.CODE_FAIL, "参数不能为空");
        }
        try {
            ckCompanyService.updateDeviceCode(excelCompanyCode, excelDeviceCode, request);
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("CkCompanyController updateDeviceCode 修改机器码文件失败：" + e.getMessage());
            return new JsonResponse(ResponseConstant.CODE_FAIL,"修改机器码文件失败");
        }
        return "";
    }

    /**
     * 导出商家关联的机器码excel文件
     * hanqr 2018-08-22
     * @param companyCode 商家代码
     * @param response
     */
    @RequestMapping("/downloadDeviceCode")
    public void downloadDeviceCode(String companyCode, HttpServletResponse response) {
        try(OutputStream out = response.getOutputStream()) {
            if(StringUtils.isBlank(companyCode)) {
                throw new ControllerException("商家代码为空");
            }
            List<CkDeviceCodeListExportVO> ckDeviceCodeExportVOList = ckCompanyService.getDeviceCodeListByCompanyCode(companyCode);
            //设置输出类型
            response.setContentType("application/vnd.ms-excel;charset=utf-8");
            //设置文件名
            response.setHeader("Content-Disposition", "attachment;filename=" + new String(("机器码.xls").getBytes(), "ISO-8859-1"));
            SimpleExportUtil.exportToExcel(ckDeviceCodeExportVOList, "机器码").write(out);
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("CkCompanyController downloadDeviceCode 导出商家关联的机器码excel文件失败:" + e.getMessage());
        }
    }
}
